﻿/*
    Copyright 2010, 2011 Eric Wong
	contact@optimalcycling.com
	http://www.optimalcycling.com
	Optimal Cycling - Advanced power pacing program for cyclists
	
	This file is part of Optimal Cycling.

    Optimal Cycling is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Optimal Cycling is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with Optimal Cycling.  If not, see <http://www.gnu.org/licenses/>.
*/

using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Text;
using System.IO;

namespace OptimalCycling.FileIO
{
    /// <summary>
    /// All file types to be dealt with by Optimal Cycling should have an entry in this enumeration.
    /// </summary>
    public enum OptimalCyclingFileFormat
    {
        Unknown,
        OptimalCyclingDataV2_0,
        OptimalCyclingDataV2_1
    }

    /// <summary>
    /// Important file constants used for all file types.
    /// </summary>
    public sealed class FileIOConstants
    {
        public const String NO_SAVE_PATH = @"NO_SAVE_PATH";
        public const String FILE_INFORMATION = @"FileInformation.csv";
        public const String DATA_FILES = @"DATA_FILES";
    }

    /// <summary>
    /// Describes the properties of a column
    /// </summary>
    public class DataColInfo
    {
        #region Properties

        string colName;
        public string ColName
        {
            get { return colName; }
        }

        Type dataType;  // bool, int, long, double, enum, string
        public Type DataType
        {
            get { return dataType; }
        }

        Object defaultVal;
        public Object DefaultVal
        {
            get { return defaultVal; }
        }

        Object lowLimit;
        public Object LowLimit
        {
            get { return lowLimit; }
        }
 
        Object highLimit;
        public Object HighLimit
        {
            get { return highLimit; }
        }

        bool sortable;
        public bool Sortable
        {
            get { return sortable; }
        }

        #endregion

        public DataColInfo(string colName, Type dataType, Object defaultVal, Object lowLimit, Object highLimit,
            bool sortable)
        {
            this.colName = colName;
            this.dataType = dataType;
            this.defaultVal = defaultVal;
            this.lowLimit = lowLimit;
            this.highLimit = highLimit;            
            this.sortable = sortable;
        }
    }

    /// <summary>
    /// Describes the properties of a table
    /// </summary>
    public class TableInfo
    {
        #region Properties

        string tableName;
        public string TableName
        {
            get { return tableName; }
        }

        DataColInfo[] dataColInfo;
        public DataColInfo[] DataColInfo
        {
            get { return dataColInfo; }
        }

        uint maxRows;
        public uint MaxRows
        {
            get { return maxRows; }
        }

        bool allowUserToAddRows;
        public bool AllowUserToAddRows
        {
            get { return allowUserToAddRows; }
        }
 
        bool allowUserToDeleteRows;
        public bool AllowUserToDeleteRows
        {
            get { return allowUserToDeleteRows; }
        }
 
        bool rowHeadersVisible;
        public bool RowHeadersVisible
        {
            get { return rowHeadersVisible; }
        }

        #endregion

        public TableInfo(string tableName, DataColInfo[] dataColInfo, uint maxRows, bool allowUserToAddRows, bool allowUserToDeleteRows,
            bool rowHeadersVisible)
        {
            this.tableName = tableName;
            this.dataColInfo = dataColInfo;
            this.maxRows = maxRows;
            this.allowUserToAddRows = allowUserToAddRows;
            this.allowUserToDeleteRows = allowUserToDeleteRows;
            this.rowHeadersVisible = rowHeadersVisible;
        }
    }

    /// <summary>
    /// Groups a set of related tables together
    /// </summary>
    public class TableGroupInfo
    {
        string tableGroupName;
        public string TableGroupName
        {
            get { return tableGroupName; }
        }

        TableInfo[] tableInfo;
        public TableInfo[] TableInfo
        {
            get { return tableInfo; }
        }

        public TableGroupInfo(string tableGroupName, TableInfo[] tableInfo)
        {
            this.tableGroupName = tableGroupName;
            this.tableInfo = tableInfo;
        }
    }

    /// <summary>
    /// Common functions used to deal with all file types.
    /// </summary>
    public class MainFileIOHandler
    {
        /// <summary>
        /// Determines the file format of a folder containing an Optimal Cycling simulation.
        /// </summary>
        /// <param name="folderPath">Full path to the folder containing the Optimal Cycling simulation.</param>
        /// <returns>Returns the Optimal Cycling file type of OptimalCyclingFileFormat, or a NotImplementedException
        /// if an error occurs.</returns>
        public static OptimalCyclingFileFormat GetOCFileFormat(String folderPath)
        {
            OptimalCyclingFileFormat formatType;
            try
            {
                String filePath = Path.Combine(folderPath, FileIOConstants.FILE_INFORMATION);
                StreamReader readTable = new StreamReader(filePath);
                DataTable tempTable = CsvParser.Parse(readTable, true);
                readTable.Close();
                formatType = (OptimalCyclingFileFormat)Enum.Parse(typeof(OptimalCyclingFileFormat),
                    tempTable.Rows[0][0].ToString());
            }
            catch (Exception)
            {
                //throw new NotImplementedException("File type not supported.");
                formatType = OptimalCyclingFileFormat.Unknown;
            }

            return formatType;
        }

    }
}
